package com.boomkeeper.ftp;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.boomkeeper.core.constant.Constant;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;

@Component
public class FtpHandler {

	private static final Logger LOGGER = LoggerFactory.getLogger(FtpHandler.class);

	private ChannelSftp channelSftp;
	
	public boolean connect(String host, String username, String password, int port) {
		boolean result = false;
		try {
			JSch jsch = new JSch();
			Session sshSession = jsch.getSession(username, host, port);
			sshSession.setPassword(password);
			sshSession.setConfig("StrictHostKeyChecking", "no");
			sshSession.connect();
			Channel channel = sshSession.openChannel("sftp");
			channel.connect();
			this.channelSftp = (ChannelSftp) channel;
			result = true;
		} catch (Exception e) {
			LOGGER.error("连接FTP服务器异常", e);
			LOGGER.error("连接FTP服务器异常，地址：{}，端口：{}，用户名：{}，密码：{}", host, port, username, password);
		}
		
		return result;
	}
	
	public void closeConnect() {
	    if (this.channelSftp != null) {
            if (this.channelSftp.isConnected()) {
            	channelSftp.disconnect();
            } else if (channelSftp.isClosed()) {
            	
            }
	    }
	}
	
	public boolean changeDirectory(String remotePath) {
		boolean result = false;
		try {
			this.channelSftp.cd(remotePath);
			result = true;
		} catch (SftpException e) {
			LOGGER.error("切换FTP路径异常", e);
		}
		
		return result;
	}
	
	public boolean upload(String localPath, String remotePath) {
		boolean result = false;
		File[] listFiles = new File(localPath).listFiles();
		for(File file : listFiles) {
			if (file.isFile()) {
				result = this.upload(file, remotePath);
			} else if(file.isDirectory()){
				String mkRemoteDir = remotePath + file.getName() + "/";
				if (this.mkdir(mkRemoteDir)) {
					result = this.upload(file.getAbsolutePath(), mkRemoteDir);
				} else {
					break;
				}
			}
		}
		
		return result;
	}
	
	public boolean upload(File file, String dest) {
		boolean result = false;
		try {
			if (file.isFile()) {
				String remoteFile = null;
				if (StringUtils.isNotBlank(dest)) {
					remoteFile = dest + file.getName();
				} else {
					remoteFile = file.getName();
				}
				result = this.upload(new FileInputStream(file), remoteFile);
			} else {
				LOGGER.error("上传文件到FTP发生错误，上传的貌似不是一个文件：{}", file.getAbsolutePath());
			}
		} catch (FileNotFoundException e) {
			LOGGER.error("上传文件到FTP发生异常", e);
			LOGGER.error("上传文件到FTP发生异常，文件不存在：{}", file.getAbsolutePath());
		}
		
		return result;
	}
	
	public boolean upload(FileInputStream fileInputStream, String dest) {
		boolean result = false;
		try {
			this.channelSftp.put(fileInputStream, dest);
			result = true;
		} catch (SftpException e) {
			LOGGER.error("上传文件到FTP发生异常", e);
			LOGGER.error("上传文件到FTP发生异常：{}", dest);
		}
		
		return result;
	}
	
	public boolean mkdir(String path) {
		boolean result = false;
		try {
			this.channelSftp.mkdir(path);
			result = true;
		} catch (SftpException e) {
			LOGGER.error("在FTP创建目录异常", e);
			LOGGER.error("在FTP创建目录异常，目录：{}", path);
		}
		
		return result;
	}
	
	public List<String> listFiles(String path) {
		List<String> fileList = new ArrayList<>(0);
		try {
			Vector<LsEntry> vector = this.channelSftp.ls(path);
			Iterator<LsEntry> iterator = vector.iterator();
			while(iterator.hasNext()) {
				LsEntry lsEntry = iterator.next();
				if (Pattern.matches(Constant.REGX_DIRECTORY, lsEntry.getFilename())) {
					fileList.add(lsEntry.getFilename());
				}
			}
		} catch (SftpException e) {
			LOGGER.error("获取FTP目录异常", e);
			LOGGER.error("获取FTP目录异常，目录：{}", path);
		}
		
		return fileList;
	}
	
	public boolean isDirExist(String remoteDir) {
		boolean isExist = false;
		try {
			SftpATTRS sftpATTRS = this.channelSftp.stat(remoteDir);
			if (sftpATTRS != null && sftpATTRS.isDir()) {
				isExist = true;
			}
		} catch (SftpException e) {
			LOGGER.error("检查远程目录是否存在时发生异常，可能不存在远程目录", e);
			LOGGER.error("检查远程目录是否存在时发生异常，可能不存在远程目录：{}", remoteDir);
		}
		
		return isExist;
	}
	
	public boolean isFileExist(String remoteFile) {
		boolean isExist = false;
		try {
			SftpATTRS sftpATTRS = this.channelSftp.stat(remoteFile);
			if (sftpATTRS != null) {
				isExist = true;
			}
		} catch (SftpException e) {
			LOGGER.error("检查远程文件是否存在时发生异常，可能不存在远程文件", e);
			LOGGER.error("检查远程文件是否存在时发生异常，可能不存在远程文件：{}", remoteFile);
		}
		
		return isExist;
	}
}
